package net.dgg.zz.common.service;


import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.alibaba.fastjson.serializer.SerializerFeature;
import net.dgg.framework.tac.utils.exception.DggBaseException;
import net.dgg.iboss.base.common.exception.BizException;
import net.dgg.iboss.base.util.JsonUtil;
import net.dgg.iboss.base.util.MapUtils;
import net.dgg.iboss.base.util.StringUtils;
import net.dgg.iboss.base.util.http.HttpUtility;
import net.dgg.iboss.base.util.http.ResultObj;
import net.dgg.tmd.foundation.platform.session.SessionManager;
import net.dgg.tmd.foundation.platform.treebook.entity.TreeBook;
import net.dgg.tmd.foundation.platform.treebook.service.TreeBookService;
import net.dgg.utils.http.DggHttpUtil;
import net.dgg.zz.common.constant.CredentialConstant;
import net.dgg.zz.common.entity.Node;
import net.dgg.zz.common.excption.CommonExcption;
import net.dgg.zz.common.utils.ValidateUtils;
import net.dgg.zz.production.entity.ProductOrder;
import net.dgg.zz.production.excption.ProcessConfigException;
import net.dgg.zz.production.excption.ProductOrderExcption;
import net.dgg.zz.production.inProcess.dao.ProductOrderDao;
import net.dgg.zz.production.inProcess.service.ZzInProcessService;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

@Service
public class FlowService {
    @Value("${scCmsUrl}")
    private  String sccmsUrl;
    @Value("${dgg.tac.microuag.domain}")
    private String gatewayBasePath;
    @Value("${dgg.appId}")
    private String shortSysCode;
    @Value("${dgg.secretKey}")
    private String shortSecret;
    private  String flowApi="/api/sc_cms/out/service/getProcessConfigByParams.do";
    @Autowired
    private ProductOrderDao productOrderDao;
    @Autowired
    private ZzInProcessService zzInProcessService;
    @Autowired
    private SessionManager sessionManager;
    @Autowired
    private TreeBookService treeBookService;

    private static Logger logger = LoggerFactory.getLogger(FlowService.class);

    /**
     * 通过接口获取公共流程节点
     * @param productIds
     * @return
     */
    @Transactional
    public List<Node> getNodeByscCmsUrl(String productIds,String businessCode,Long businessOrgId,String businessProductCode){
        Map<String,Object> resultMap = new HashMap<String,Object>();
        resultMap = this.findNode(productIds,businessCode,businessOrgId,businessProductCode);
        if(resultMap==null){
            throw new CommonExcption("没有获取到流程节点,请先配置");
        }
        List<Map<String, Object>> nodeList = new ArrayList<Map<String, Object>>();
        List <Node> nodeList1=new ArrayList<>();
        nodeList = (List) resultMap.get("nodeDtoList");
        for( int i = 0; i < nodeList.size(); i++ ) {
            Node node = new Node();
            MapUtils.map2Bean(node, (Map<String, Object>) nodeList.get(i));
            nodeList1.add(node);
        }
        return nodeList1;
    }

    /**
     * 获取公共流程配置节点
     * @param productIds
     * @return
     */
    public Map findNode(String productIds,String businessCode,Long businessOrgId,String businessProductCode) {
        Map reMap = new HashMap(16);
        try {
            String nodeStr = this.getFlowNodeStr(productIds,businessCode,businessOrgId,businessProductCode);
            ResultObj resultObj = JsonUtil.json2Obj(nodeStr, ResultObj.class);
            reMap = JsonUtil.json2Obj(resultObj.getData(), Map.class);
        }catch (Exception e){
            e.getMessage();
        }


        return reMap;
    }

    /**
     * 通过生产订单id获取流程节点
     * @param id
     * @return
     */
    @Transactional
    public List<Node> getNode(Long id){
        List<Node> list = new ArrayList<>();
        ProductOrder productOrder = productOrderDao.selectByPrimaryKey(id);
        Map nodeMap = getCurrentNode(productOrder);
        List<Node> listNew = new ArrayList<>();
        if(StringUtils.isEmpty(productOrder.getFlowContent())){
            try {
                list= this.getNodeByscCmsUrl(productOrder.getProductId().toString(),productOrder.getBusinessTypeCode(),productOrder.getProductOrgId(),productOrder.getBusinessProductCode());
            }catch (Exception e){
                throw new CommonExcption("分配失败：未查询到{"+productOrder.getProductName()+"}流程节点的配置信息，请联系管理员进行配置");
            }
        }else {
            list = this.getNodeByFlowContent(productOrder.getFlowContent());
        }
//       if(list.size()>0){
//           for (Node node : list) {
//               if(!nodeMap.get("name").equals("公示") || !nodeMap.get("name").equals("通告")){
//                   if(!node.getCode().equals(nodeMap.get("code"))){
//                       listNew.add(node);
//                   }
//               }else{
//                   listNew.add(node);
//               }
//           }
//       }
        return list;
    }

    /**
     * 通过订单表里保存的流程数据获取流程节点
     * @param flowContent
     * @return
     */

    public List<Node> getNodeByFlowContent(String flowContent){
        if(StringUtils.isEmpty(flowContent)){
            return null;
        }

        JSONObject resultObj = JSONObject.parseObject(flowContent);
        boolean b = false;
        if(!StringUtils.isEmptyObj(resultObj.getString("data"))){
            resultObj = (JSONObject) resultObj.get("data");
            b = true;
        }
        List<Map<String, Object>> nodeDtoList = (List) resultObj.get("nodeDtoList");
        List <Node> nodeList = new ArrayList<>();
        for( int i = 0; i < nodeDtoList.size(); i++ ) {
            Node node = new Node();
            node.setId(Long.parseLong(String.valueOf(nodeDtoList.get(i).get("id"))));
            String name;
            Integer cycleType;
            Integer isKeyTask;
            Integer handleDate;
            Integer isPunish;
            if(b){
                //老模班取对应数据
                name = String.valueOf(nodeDtoList.get(i).get("name"));
                cycleType = Integer.parseInt(String.valueOf(nodeDtoList.get(i).get("isNaturalorWorkday")));
                isKeyTask = Integer.parseInt(String.valueOf(nodeDtoList.get(i).get("isKey")));
                handleDate = Integer.parseInt(String.valueOf(nodeDtoList.get(i).get("handleDate")));
                isPunish = Integer.parseInt(String.valueOf(nodeDtoList.get(i).get("isPunish")));
            }else{
                //新模板取对应数据
                name = String.valueOf(nodeDtoList.get(i).get("taskName"));
                cycleType = Integer.parseInt(String.valueOf(nodeDtoList.get(i).get("cycleType").equals("WORK_DAY") ? 1 : 2));
                isKeyTask = Integer.parseInt(String.valueOf(nodeDtoList.get(i).get("isKeyTask"))) == 0 ? 2 : 1;
                handleDate = Integer.parseInt(String.valueOf(nodeDtoList.get(i).get("processingCycle"))) * 24;
                //新模板没有扣罚字段，默认 2为不扣罚
                isPunish = 2;
            }
            node.setName(name);
            //新的企大宝任务节点没有code，暂时存节点name
            node.setCode(name);
            node.setIsNaturalorWorkday(cycleType);
            node.setIsKey(isKeyTask);
            node.setIsMust(isKeyTask);
            node.setHandleDate(handleDate);
            node.setIsPunish(isPunish);
            //node.setRelationFieldIds(String.valueOf(nodeDtoList.get(i).get("relationFieldJson"))); 关联字段
            node.setSort(Integer.parseInt(String.valueOf(nodeDtoList.get(i).get("sort"))));
            node.setProcessCode(String.valueOf(nodeDtoList.get(i).get("processId")));
            //任务默认为启用状态
            node.setFlag(1);
            node.setCommission(String.valueOf(nodeDtoList.get(i).get("commission")));
            String brokerage = "0";
            if(!StringUtils.isEmptyObj(nodeDtoList.get(i).get("brokerage"))){
                brokerage = String.valueOf(nodeDtoList.get(i).get("brokerage"));
            }
            node.setBrokerage(new BigDecimal(brokerage));
            nodeList.add(node);
        }
        return nodeList;
    }

    /**
     * 获取当前节点
     * @param productOrder
     * @return
     */
    public Map getCurrentNode(ProductOrder productOrder){
        Map nodeMap = new HashMap();
        nodeMap.put("id",productOrder.getCurrentNodeId());
        nodeMap.put("name",productOrder.getCurrentNodeName());
        return nodeMap;
    }

    /**
     * 获取公共流程节点信息的字符串
     * @param productIds
     * @param businessCode
     * @return
     */
    public String getFlowNodeStr(String productIds,String businessCode,Long businessOrgId,String smallBusinessTypeCode){
        String resultStr = "";
        //根据产品id、业态code查询模板信息
        Map param = new HashMap(10);
        //根据事业部id查询对应区域
        TreeBook treeBook = treeBookService.getTreeBookByCode(String.valueOf(businessOrgId));
        if(StringUtils.isNotBlankObj(treeBook) && StringUtils.isNotBlank(treeBook.getExt1())){
            param.put("districtCode",treeBook.getExt1());
        }
        param.put("productId", productIds);
        param.put("businessTypeCode", businessCode);
        param.put("smallBusinessTypeCode",smallBusinessTypeCode);

        Map<String, String> header = new HashMap<>(10);
        header.put("x-auth-token", String.valueOf(sessionManager.getCurrentSessionId()));
        String templateStr = DggHttpUtil.doPostJsonByGateway(gatewayBasePath + "qdstemplate/api/white/template_config/v2/search_template.do",
                shortSysCode, shortSecret, header, param, null);
        logger.info("获取模板信息{}",templateStr);
        if (StringUtils.isEmpty(templateStr)) {
            throw new ProcessConfigException("查询企大宝任务模板失败，请稍后再试");
        }

        JSONObject templateObj = JSONObject.parseObject(templateStr);
        if (templateObj.getInteger("code") != 200) {
            throw new ProcessConfigException(templateObj.getString("msg"));
        }
        JSONArray records = templateObj.getJSONObject("data").getJSONArray("records");
        if (StringUtils.isEmptyObj(records) || records.size() < 1) {
            throw new ProcessConfigException("任务模板中未获取对应流程配置");
        }
        //获取模板信息对象
        JSONObject record = records.getJSONObject(0);
        if("".equals(record.getString("cycleType")) || "小时".contains(record.getString("cycleType"))){
            throw new ProcessConfigException("任务周期暂不支持此类任务周期");
        }

        //根据模板主键id查询对应的阶段及节点信息
        String nodeStr = DggHttpUtil.doGetByGateway(gatewayBasePath + "qdstemplate/api/white/template_config/query_template.do?processId="+record.get("id"),
                shortSysCode, shortSecret, header, null);
        logger.info("获取流程节点信息{}",nodeStr);
        if (StringUtils.isEmpty(nodeStr)) {
            throw new ProcessConfigException("根据模板id获取对应流程节点信息失败，请稍后再试");
        }
        JSONObject nodeObj = JSONObject.parseObject(nodeStr);
        if (nodeObj.getInteger("code") != 200) {
            throw new ProcessConfigException(nodeObj.getString("msg"));
        }
        //解析节点信息json，获取阶段信息
        JSONArray stageLawVos = nodeObj.getJSONObject("data").getJSONArray("stageLawVos");
        if(stageLawVos.size() > 1){
            throw new ProcessConfigException("该任务模板包含了多个阶段，请联系管理员");
        }
        List nodeDtoList = new ArrayList();
        //TODO 多阶段的时候，循环各阶段获取任务节点
        for (int i = 0;i < stageLawVos.size();i++ ){
            //获取各阶段下的任务节点
            JSONArray taskLawVos = stageLawVos.getJSONObject(i).getJSONArray("taskLawVos");
            for(int j = 0;j < taskLawVos.size();j++ ){
                JSONObject templateTask = taskLawVos.getJSONObject(j).getJSONObject("templateTask");
                String cycleType = templateTask.getString("cycleType");
                if(StringUtils.isNotEmpty(cycleType)){
                    if(!"WORK_DAY".equals(cycleType) && !"NATURAL_DAY".equals(cycleType)){
                        throw new CommonExcption("节点周期只能是工作日和自然日！");
                    }
                }else{
                    throw new CommonExcption("任务节点必须选择任务周期！");
                }
                if(StringUtils.isEmptyObj(templateTask.get("processingCycle"))){
                    throw new ProcessConfigException("任务节点必须填写周期时间");
                }
                //放进数组
                nodeDtoList.add(templateTask);
            }
        }
        //封装任务节点数据到模板数据上
        record.put("cycleType",record.get("cycleType").equals("WORK_DAY") ? 1 : 2);
        record.put("handleDate",Integer.parseInt(String.valueOf(record.get("processingCycle"))) * 24);
        record.put("name",record.get("taskName"));
        record.put("nodeDtoList",nodeDtoList);
        //转换成json字符串
        resultStr = JSON.toJSONString(record,SerializerFeature.WriteMapNullValue);
        return resultStr;
    }

    /**
     * 根据nodeId,生产id 获取 节点信息
     * @param nodeId
     * @param id
     * @return
     */
    public Node queyNodeListById(String nodeId,Long id){
        List<Node> list = this.getNode(id);
        Node returnNode = new Node();
        if(list.size()>0){
            for (Node node : list) {
                if(nodeId.equals(node.getId().toString())){
                    returnNode = node;
                    break;
                }
            }
        }
        return returnNode;
    }
    /**
     * 根据nodeId,生产id 获取 节点信息
     * @param nodeName
     * @param id
     * @return
     */
    public Node queyNodeListByName(String nodeName,Long id){
        List<Node> list = this.getNode(id);
        Node returnNode = new Node();
        if(list.size()>0){
            for (Node node : list) {
                if(nodeName.equals(node.getName())){
                    returnNode = node;
                    break;
                }
            }
        }
        return returnNode;
    }

    /**
     * 根据当前node 获取下一个关键节点
     * @param nodeId
     * @param id
     * @return
     */
    public Node getNextMustNode(String nodeId,Long id){
        if(StringUtils.isEmpty(nodeId) || null == id){
            return null;
        }
        List<Node> list = this.getNode(id);
        Node returnNode = new Node();
        Integer sort = 1000;
        if(list.size()>0){
            for (Node node : list) {
                if(nodeId.equals(node.getId().toString())){
                    sort = node.getSort();
                }
                if(node.getSort()>sort && node.getIsKey()==1){
                    returnNode = node;
                    break;
                }
            }
        }
        return returnNode;
    }

    /**
     * 通过生产订单id获取流程关键节点
     * @param id
     * @return
     */
    public List<Node> getKeyNode(Long id){
        List<Node> list = new ArrayList<>();
        ProductOrder productOrder = productOrderDao.selectByPrimaryKey(id);
        Map nodeMap = getCurrentNode(productOrder);
        List<Node> listNew = new ArrayList<>();
        if(StringUtils.isEmpty(productOrder.getFlowContent())){
            list= this.getNodeByscCmsUrl(productOrder.getProductId().toString(),productOrder.getBusinessTypeCode(),productOrder.getProductOrgId(),productOrder.getBusinessProductCode());
        }else {
            list = this.getNodeByFlowContent(productOrder.getFlowContent());
        }
        if(list.size()>0){
            for (Node node : list) {
                if(node.getIsKey()==1){
                    listNew.add(node);
                }
            }
        }
        return listNew;
    }

    /**
     * 获取订单当前节点之后的关键节点
     * @param id
     * @return
     */
    public List<Node> getAfterKeyNode(Long id,List<String> nodeNamelist){
        List<Node> list = new ArrayList<>();
        ProductOrder productOrder = productOrderDao.selectByPrimaryKey(id);
        String currentNodeName = productOrder.getCurrentNodeName();
        List<Node> listNew = new ArrayList<>();
        if(StringUtils.isEmpty(productOrder.getFlowContent())){
            list= this.getNodeByscCmsUrl(productOrder.getProductId().toString(),productOrder.getBusinessTypeCode(),productOrder.getProductOrgId(),productOrder.getBusinessProductCode());
        }else {
            list = this.getNodeByFlowContent(productOrder.getFlowContent());
        }
        if(list.size()>0){
            Integer sort=100;
            for (Node node : list) {
                if(!productOrder.getLatestEndNodeName().equals("完结")) {
                    if (node.getName().equals(currentNodeName) && !nodeNamelist.contains(node.getName())) {
                        sort = node.getSort();
                        listNew.add(node);
                    }
                    if (node.getIsKey() == 1 && node.getSort() > sort && !nodeNamelist.contains(node.getName())) {
                        listNew.add(node);
                    }
                }
            }
        }
        return listNew;
    }

    /**
     * 获取订单流程的周期时间
     * @param order
     * @return
     */
    public Map getOderCycle(ProductOrder order) {
        Map returnMap = new HashMap();
        Map reMap = new HashMap();
        String str = null;
        if (StringUtils.isEmpty(order.getFlowContent())) {
            str = this.getFlowNodeStr(order.getProductId().toString(),order.getBusinessTypeCode(),order.getProductOrgId(),order.getBusinessProductCode());
        }else{
            str=order.getFlowContent();
        }
        if(!StringUtils.isEmpty(str)) {
            JSONObject resultObj = JSONObject.parseObject(str);
            returnMap.put("processingCycle",resultObj.get("handleDate"));
            returnMap.put("cycleType",resultObj.get("cycleType"));
        }
        return returnMap;
    }
}
